home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / vtkerma2.arc / MSXRB.ASM < prev    next >
Encoding:
Assembly Source File  |  1986-02-13  |  41.6 KB  |  1,535 lines

  1.     PAGE 59, 132
  2.  
  3.     TITLE MSXRB -- Machine dependent module for DEC Rainbow
  4.  
  5. ; Update 23 Nov 85
  6.  
  7. IF1
  8.  %OUT >> Starting pass 1
  9. ELSE
  10.  %OUT >> Starting pass 2
  11. ENDIF
  12.  
  13. ; Kermit system dependent module for Rainbow
  14. ; Jeff Damens, July 1984
  15.  
  16.     public    SerIni_RB, SerRst_RB, ClrBuf_RB, OutChr_RB, Coms_RB
  17.     public    VTS_RB, DoDel_RB, CtlU_RB, CmBlnk_RB, Locate_RB
  18.     public    LclIni_RB, PrtChr_RB, DoBaud_RB, ClearL_RB, Drop_DTR_RB
  19.     public    DoDisk_RB, GetBaud_RB, Beep_RB, Close_screen_RB
  20.     public    PutHlp_RB, PutMod_RB, ClrMod_RB, PosCur_RB
  21.     public    SendBR_RB, Term_RB, SetKTab_RB, SetKHlp_RB, ShowKey_RB
  22.     PUBLIC Set_up_script_processor_RB
  23.     include msdefs.h
  24.  
  25. ; rainbow-dependent screen constants
  26.  
  27. scrseg    equ    0ee00H        ; screen segment
  28. latofs    equ    0ef4h        ; ptrs to line beginnings, used by firmware
  29. csrlin    equ    0f42h        ; current cursor line.
  30.  
  31. ; level 1 console definitions
  32.  
  33. fnkey    equ    100H        ; function key flag
  34. shfkey    equ    200H        ; shift key
  35. ctlkey    equ    400H        ; control key
  36. cplk    equ    800H
  37.  
  38. brkkey    equ    65H
  39. prtkey    equ    3
  40. Cntrl_E    EQU    5
  41.  
  42. false    equ    0
  43. true    equ    1
  44. mntrgh    equ    bufsiz*3/4    ; High point = 3/4 of buffer full.
  45.  
  46. mnstata    equ    042H        ;Status/command port A
  47. mnstatb    equ    043H        ;Status/command port B.
  48. mndata    equ    040H        ;Data port.
  49. mndatb    equ    041H
  50. mnctrl    equ    002H        ;Control port.
  51. serchn    equ    0A4H        ; interrupt to use
  52. serch1    equ    044H        ; use this too for older rainbows.
  53.  
  54. txrdy    EQU    04H        ;Bit for output ready.
  55. rxrdy    EQU    01H        ;Bit for input ready.
  56.  
  57. fastcon    equ    29H        ; fast console handler
  58. firmwr    equ    18H
  59.  
  60. swidth    equ    132        ; screen width
  61. slen    equ    24        ; screen length
  62.  
  63. stbrk    equ    15        ; start sending a break
  64. enbrk    equ    16        ; stop sending break.
  65.  
  66. ; external variables used:
  67. ; drives - # of disk drives on system
  68. ; flags - global flags as per flginfo structure defined in pcdefs
  69. ; trans - global transmission parameters, trinfo struct defined in pcdefs
  70. ; portval - pointer to current portinfo structure (currently either port1
  71. ;    or port2)
  72. ; port1, port2 - portinfo structures for the corresponding ports
  73.  
  74. ; global variables defined in this module:
  75. ; xofsnt, xofrcv - tell whether we saw or sent an xoff.
  76.  
  77. ; circular buffer ptr
  78. cbuf    struc
  79. pp    dw    ?            ; place ptr in buffer
  80. bend    dw    ?            ; end of buffer
  81. orig    dw    ?            ; buffer origin
  82. lcnt    dw    0            ; # of lines in buffer.
  83. cbuf    ends
  84.  
  85. ; answerback structure
  86. ans    struc
  87. anspt    dw    ?            ; current pointer in answerback
  88. ansct    db    ?            ; count of chars in answerback
  89. ansseq    dw    ?            ; pointer to whole answerback
  90. anslen    db    ?            ; original length
  91. ansrtn    dw    ?            ; routine to call.
  92. ans    ends
  93.  
  94. datas     segment    public 'datas'
  95.     extrn    drives:byte,flags:byte, trans:byte, Source:BYTE
  96.     extrn    portval:word, port1:byte, port2:byte, SrcPnt:WORD
  97.     EXTRN    Count:WORD, XofSnt:BYTE
  98.  
  99. Escape_key_mode_line db ' ? = Help C = Close S = Status B = Send Break  ? For Full List$'
  100.  
  101. Terminal_message db '( Entering terminal mode:',cr,lf,' Press <Do> or Ctrl-] C  to return to Local BTLink )',cr,lf,'$'
  102.  
  103. SetKTab_RB DB    22
  104.     mkeyw    'F4',fnkey+5h
  105.     mkeyw    'F5',fnkey+65h
  106.     mkeyw    'F6',fnkey+7h
  107.     mkeyw    'F7',fnkey+9h
  108.     mkeyw    'F8',fnkey+0Bh
  109.     mkeyw    'F9',fnkey+0Dh
  110.     mkeyw    'F10',fnkey+0Fh
  111.     mkeyw    'F11',esc
  112.     mkeyw    'F12',bs
  113.     mkeyw    'F13',lf
  114.     mkeyw    'F14',fnkey+11h
  115.     mkeyw    'F17',fnkey+13h
  116.     mkeyw    'F18',fnkey+15h
  117.     mkeyw    'F19',fnkey+17h
  118.     mkeyw    'F20',fnkey+19h
  119.     mkeyw    'FIND',fnkey+1bh
  120.     mkeyw    'INSERTHERE',fnkey+1dh
  121.     mkeyw    'REMOVE',fnkey+1fh
  122.     mkeyw    'SCAN',-1
  123.     mkeyw    'SELECT',fnkey+21h
  124.  
  125. Seventy_nine_blanks_then_cr DB 79 DUP(' '), Cr, '$'
  126.  
  127. ourflgs    db    Which_mode    ; our flags
  128.                 ; flag definitions...
  129. fpscr    equ    80H        ; Flag for Ctrl-Print-Screen functionality
  130. MC_Pcon    equ    40H        ; Flag for Printer Controller (MC)
  131.                 ;  escape sequence processing
  132. Which_mode EQU 20H        ; Flag that we are really at "BTLink> " screen
  133.                 ;  instead of terminal emulation screen
  134.  
  135. crlf    db    cr,lf
  136. SetKHlp_RB DB    ' F4 ... F20 or SCAN$'
  137. nyimsg    db    cr,lf,'Not yet implemented$'
  138. delstr  db      BS,' ',BS,'$'     ; Delete string.
  139. clrlin  db      cr,'$'        ; Clear line (just the cr part).
  140. oldser    dw    ?        ; old serial handler
  141. oldseg    dw    ?        ; segment of above
  142. old1ser    dw    ?        ; old serial handler, alternate address
  143. old1seg    dw    ?        ; segment of same.
  144. portin    db    0        ; Has comm port been initialized.
  145. xofrcv    db    0        ; Say if we received an XOFF.
  146. iobuf    db    5 dup (?)    ; buffer for ioctl
  147.  
  148. phbuf    db    swidth dup (?)
  149. gopos    db    esc,'['
  150. rowp    db    20 dup (?)
  151. clrseq    db    esc,'[H',esc,'[J$'
  152. ceolseq    db    esc,'[K$'
  153. invseq    db    esc,'[7m$'
  154. nrmseq    db    esc,'[0m$'
  155. ivlatt    db    swidth dup (0fH) ; a line's worth of inverse attribute
  156.  
  157. ; special keys.
  158. spckey    dw    brkkey,prtkey,prtkey+ctlkey
  159. spclen    equ    ($-spckey)/2
  160. ; special key handlers.  Must parallel spckey
  161. spchnd    dw    SendBR_RB,prtscr,togprt
  162.  
  163. ; arrow and PF keys
  164. arrkey    db    27H,29H,2bH,2dH,59H,5cH,5fH,62H
  165. arrlen    equ    $-arrkey
  166. ; translations for arrow and PF keys, must parallel arrkey
  167. arrtrn    dw    uptrn,dntrn,rgttrn,lfttrn
  168.     dw    pf1trn,pf2trn,pf3trn,pf4trn
  169.  
  170. ; keypad keys
  171. keypad    db    2fh,32h,35h,38h,3bh,3eh,41h,44h,47h,4ah,4dh,50h,53h,56h
  172. keypln    equ    $-keypad
  173. ; keytrn and altktrn must parallel keypad
  174. keytrn    db    '0123456789-,.',cr
  175. altktrn    db    'pqrstuvwxymlnM'
  176.  
  177. keyptr    dw    keytrn        ; pointer to correct translation table
  178. akeyflg    db    0        ; non-zero if in alt keypad mode.
  179.  
  180. ; arrow and PF key translations
  181. uptrn    db    3,esc,'[A'
  182. dntrn    db    3,esc,'[B'
  183. rgttrn    db    3,esc,'[C'
  184. lfttrn    db    3,esc,'[D'
  185. pf1trn    db    3,esc,'OP'
  186. pf2trn    db    3,esc,'OQ'
  187. pf3trn    db    3,esc,'OR'
  188. pf4trn    db    3,esc,'OS'
  189.  
  190. ourarg    termarg    <>
  191.  
  192.     EVEN
  193.  
  194. Script_processor DW 0        ; Address of script processor to run
  195.  
  196. ; variables for serial interrupt handler
  197. savesi    dw    0        ; Save SI register here.    
  198.  
  199. telflg    db    0        ; non-zero if we're a terminal. NRU.
  200. respkt    db    10 dup (?)    ; ioctl packet
  201.  
  202. ivec    dw    tranb        ; transmit empty B
  203.     dw    tranb        ; status change B
  204.     dw    tranb        ; receive b
  205.     dw    tranb        ; special receive b
  206.     dw    stxa        ; transmit empty a
  207.     dw    sstata        ; status change a
  208.     dw    srcva        ; receive a
  209.     dw    srcva        ; special receive a
  210.  
  211. ; screen stuff
  212.  
  213. prbuf    db    swidth dup (?)    ; print temp buffer
  214. topdwn    db    esc,'[H',esc,'M$' ; go to top, scroll down
  215. botup    db    esc,'[24;0H',esc,'D$' ; go to bottom, scroll up
  216. curinq    db    esc,'[6n$'    ; cursor inquiry
  217. posbuf    db    12 dup (?)    ; place to store cursor position
  218. command_posbuf    db 12 dup (?)    ; place to store BTLink
  219.                 ; command screen cursor position
  220. gtobot    db    esc,'[24;0H$'    ; go to bottom of screen.
  221. ourscr    db    slen*swidth dup (?)
  222. ourattr    db    slen*swidth dup (?) ; storage for screen and attributes
  223. command_mode_screen    db slen*swidth dup (?) ; buffer for screen
  224. command_mode_attrs    db slen*swidth dup (?) ; buffer for attribute
  225. inited    db    0        ; terminal handler not inited yet.
  226. dosmsg    db    '?Must be run in version 2.05 or higher$'
  227. anssq1    db    esc,'[5i'    ; Turn Printer Controller on
  228. ansln1    equ    $-anssq1
  229. anssq2    db    esc,'[4i'    ; Turn Printer Controller off
  230. ansln2    equ    $-anssq2
  231. eakseq    db    esc,'='
  232. dakseq    db    esc,'>'
  233. Do_Server_mode_Sq DB ESC,'[17J'
  234. Req_to_ident_seq DB ESC,'[18J'
  235. Identification_sequence DB ESC,'[?99c'
  236. Length_of_identification_sequence EQU $-Identification_sequence
  237. ansbk1    ans    <anssq1,ansln1,anssq1,ansln1,Printer_Controller_MC>
  238. ansbk2    ans    <anssq2,ansln2,anssq2,ansln2,Printer_Controller_MC>
  239. ansbk3    ans    <eakseq,2,eakseq,2,enaaky> ; enable alt keypad
  240. ansbk4    ans    <dakseq,2,dakseq,2,deaaky> ; disable alt keypad
  241. ansbk5    ans <Do_Server_mode_Sq,5,Do_Server_mode_Sq,5,Do_Server_mode>
  242. ansbk6    ans <Req_to_ident_seq,5,Req_to_ident_seq,5,Identify>
  243. Partial_esc_seq DB ESC,'[17$'    ; For TSMG typing in Do_Server_mode
  244.  
  245. shkbuf    db    300 dup (?)    ; room for definition
  246. shkmsg    db    '  Scan code: '
  247. shkmln    equ    $-shkmsg
  248. shkms1    db    cr,lf,'  Definition: '
  249. shkm1ln    equ    $-shkms1
  250. datas    ends
  251.  
  252. code    segment    public
  253.     extrn    Quit_emulator:BYTE, comnd:near, dopar:near, Enter_Server:NEAR
  254.     assume    cs:code,ds:datas
  255.  
  256. ; local initialization routine, called by Kermit initialization.
  257.  
  258. LclIni_RB    proc    near
  259. ; make sure this is DOS version 2.05 or higher...
  260.     mov    ah,dosver
  261.     int    dos
  262.     xchg    al,ah        ; put major version in ah, minor in al
  263.     cmp    ax,205H        ; is it 2.05?
  264.     jae    lclin1        ; yes, go on
  265.     mov    dx,offset dosmsg
  266.     call    tmsg
  267.     mov    ax,4c00H    ; exit(0)
  268.     int    dos
  269. lclin1:    mov    flags.vtflg,0    ; turn off heath emulation
  270.     ret
  271. LclIni_RB    endp
  272.  
  273. ; this is called by Kermit initialization.  It checks the
  274. ; number of disks on the system, sets the drives variable
  275. ; appropriately.  The only problem is that a value of two
  276. ; is returned for single drive systems to be consistent
  277. ; with the idea of the system having logical drives A and
  278. ; B.  Returns normally.  
  279.  
  280. DoDisk_RB    PROC    NEAR
  281.     mov ah,gcurdsk            ; Current disk value to AL.
  282.     int dos
  283.     mov dl,al            ; Put current disk in DL.
  284.     mov ah,seldsk            ; Select current disk.
  285.     int dos                ; Get number of drives in AL.
  286.     mov drives,al
  287.     ret
  288. DoDisk_RB    ENDP
  289.  
  290. ; show the definition of a key.  The terminal argument block (which contains
  291. ; the address and length of the definition tables) is passed in ax.
  292. ; Returns a string to print in AX, length of same in CX.
  293. ; Returns normally.
  294. ShowKey_RB    proc    near
  295.     push    es
  296.     push    ax        ; save the ptr
  297.     cld
  298. showk1:    mov    di,6        ; get level one char
  299.     int    firmwr
  300.     cmp    cl,0ffH
  301.     jne    showk1        ; wait until char available
  302.     mov    bx,ds
  303.     mov    es,bx        ; address data segment
  304.     and    ax,not cplk    ; no caps lock
  305.     push    ax        ; remember scan code
  306.     mov    di,offset shkbuf
  307.     mov    si,offset shkmsg
  308.     mov    cx,shkmln
  309.     rep    movsb        ; copy in initial message
  310.     call    nout        ; write out scan code
  311.     mov    si,offset shkms1
  312.     mov    cx,shkm1ln    ; second message
  313.     rep    movsb
  314.     pop    ax        ; get scan code back
  315.     pop    bx        ; and terminal arg block
  316.     mov    cx,[bx].klen    ; and length
  317.     jcxz    showk2        ; no table, not defined
  318.     push    di        ; remember output ptr
  319.     mov    di,[bx].ktab    ; get key table
  320.     repne    scasw        ; search for a definition for this
  321.     mov    si,di        ; remember result ptr
  322.     pop    di        ; get output ptr back
  323.     jne    showk2        ; not defined, forget it
  324.     sub    si,[bx].ktab    ; compute offset from beginning
  325.     sub    si,2        ; minus 2 for pre-increment
  326.     add    si,[bx].krpl    ; get index into replacement table
  327.     mov    si,[si]        ; pick up replacement
  328.     mov    cl,[si]        ; get length
  329.     mov    ch,0
  330.     inc    si
  331.     rep    movsb        ; copy into buffer
  332. showk2:    mov    ax,offset shkbuf ; this is buffer
  333.     mov    cx,di
  334.     sub    cx,ax        ; length
  335.     pop    es
  336.     ret            ; and return
  337. ShowKey_RB    endp
  338.  
  339. ; Clear the input buffer. This throws away all the characters in the
  340. ; serial interrupt buffer.  This is particularly important when
  341. ; talking to servers, since NAKs can accumulate in the buffer.
  342. ; Returns normally.
  343.  
  344. ClrBuf_RB    PROC    NEAR
  345.     cli
  346.     mov ax,offset Source
  347.     mov srcpnt,ax
  348.     mov savesi,ax
  349.     mov count,0
  350.     sti
  351.     ret
  352. ClrBuf_RB    ENDP
  353.  
  354. ; Clear to the end of the current line.  Returns normally.
  355.  
  356. ClearL_RB    PROC    NEAR
  357.     mov    dx,offset ceolseq    ; clear sequence
  358.     jmp    tmsg
  359. ClearL_RB    ENDP
  360.  
  361. ; Put the char in AH to the serial port.  This assumes the
  362. ; port has been initialized.  Should honor xon/xoff.  Skip returns on
  363. ; success, returns normally if the character cannot be written.
  364.  
  365. OutChr_RB:
  366.     mov bp,portval
  367.     cmp ds:[bp].floflg,0    ; Are we doing flow control.
  368.     je outch2        ; No, just continue.
  369.     xor cx,cx        ; clear counter
  370. outch1:    cmp xofrcv,true        ; Are we being held?
  371.     jne outch2        ; No - it's OK to go on.
  372.     loop outch1        ; held, try for a while
  373.     mov xofrcv,false    ; timed out, force it off and fall thru.
  374. outch2:    push dx            ; Save register.
  375.     sub cx,cx
  376.     mov al,ah        ; Parity routine works on AL.
  377.     call dopar        ; Set parity appropriately.
  378.     mov ah,al        ; Don't overwrite character with status.
  379.     mov dx,mnstata        ; port status register
  380. outch3:    in al,dx
  381.     test al,txrdy        ; Transmitter ready?
  382.     jnz outch4        ; Yes
  383.     loop outch3
  384.      jmp outch5        ; Timeout
  385. outch4:    mov al,ah        ; Now send it out
  386.     mov dx,mndata
  387.     out dx,al
  388.     pop dx
  389.     jmp rskp
  390. outch5:    pop dx
  391.     ret
  392.  
  393. ; This routine blanks the screen.  Returns normally.
  394.  
  395. CmBlnk_RB    PROC    NEAR
  396.     mov    dx,offset clrseq ; clear screen sequence
  397.     jmp    tmsg
  398. CmBlnk_RB  ENDP
  399.  
  400. ; Locate_RB; homes the cursor.  Returns normally.
  401.  
  402. Locate_RB  PROC    NEAR
  403.     mov dx,0        ; Go to top left corner of screen.
  404.     jmp PosCur_RB
  405. Locate_RB  ENDP
  406.  
  407. ; write a line in inverse video at the bottom of the screen...
  408. ; the line is passed in dx, terminated by a $.  Returns normally.
  409.  
  410. PutMod_RB    proc    near
  411.  
  412.     push    dx        ; preserve message
  413.     mov    dx,24 * 100H    ; line 24
  414.     call    PosCur_RB
  415.     mov    dx,offset invseq ; put into inverse video
  416.     call    tmsg
  417.     mov    dx, OFFSET Seventy_nine_blanks_then_cr ; Blank the line
  418.     call    tmsg
  419.     pop    dx
  420.     call    tmsg        ; print the message
  421.     mov    dx,offset nrmseq ; normal video
  422.     jmp    tmsg
  423.  
  424. PutMod_RB    endp
  425.  
  426. ; clear the mode line written by PutMod_RB.  Returns normally.
  427. ClrMod_RB    proc    near
  428.     mov    dx,24 * 100H
  429.     call    PosCur_RB
  430.     call    ClearL_RB
  431.     ret
  432. ClrMod_RB    endp
  433.  
  434. ; Put a help message on the screen.  This one uses reverse video...
  435. ; pass the message in ax, terminated by a null.  Returns normally.
  436. PutHlp_RB    proc    near
  437.     push    ax
  438.     mov    dx,slen * 100H    ; go to bottom line
  439.     call    PosCur_RB
  440.     pop    ax
  441.     push    es
  442.     mov    bx,ds
  443.     mov    es,bx        ; address data segment
  444.     mov    si,ax        ; convenient place for this
  445.     mov    bx,101H        ; current line/position
  446. puthl1:    mov    di,offset phbuf    ; this is destination
  447.     xor    cx,cx        ; # of chars in the line
  448. puthl2:    lodsb            ; get a byte
  449.     cmp    al,cr        ; carriage return?
  450.     je    puthl2        ; yes, ignore it
  451.     cmp    al,lf        ; linefeed?
  452.     je    puthl3        ; yes, break the loop
  453.     cmp    al,0
  454.     je    puthl3        ; ditto for null
  455.     dec    cx        ; else count the character
  456.     stosb            ; deposit into the buffer
  457.     jmp    puthl2        ; and keep going
  458. puthl3:    add    cx,80        ; this is desired length of the whole
  459.     mov    al,' '
  460.     rep    stosb        ; fill the line
  461.     push    bx
  462.     push    si
  463.     push    es        ; firmware likes to eat this one
  464.     mov    ax,0        ; send chars and attributes
  465.     mov    cx,80        ; this is # of chars to send
  466.     mov    dx,offset ivlatt ; this are attributes to send
  467.     mov    si,offset phbuf    ; the actual message
  468.     mov    di,14H        ; send direct to screen
  469.     mov    bp,ds        ; need data segment as well
  470.     int    firmwr        ; go send it
  471.     pop    es
  472.     pop    si
  473.     pop    bx        ; restore everything
  474.     inc    bx        ; next line
  475.     cmp    byte ptr [si-1],0 ; were we ended by a 0 last time?
  476.     jne    puthl1        ; no, keep looping
  477.     pop    es        ; else restore this
  478.     ret            ; and return
  479. PutHlp_RB    endp
  480.  
  481. ; Set the baud rate for the current port, based on the value
  482. ; in the portinfo structure.  Returns normally.
  483.  
  484. ; no baud rate.
  485. DoBaud_RB    PROC    NEAR
  486.     mov    dx,offset nyimsg
  487.     call    tmsg
  488.     mov    bx,portval
  489.     mov    [bx].baud,-1        ; keep baud rate unknown.
  490.     ret
  491. DoBaud_RB    ENDP
  492.  
  493. ; Get the current baud rate from the serial card and set it
  494. ; in the portinfo structure for the current port.  Returns normally.
  495. ; This is used during initialization.
  496.  
  497. GetBaud_RB    PROC    NEAR
  498.     ret            ; no baud rate for now.
  499. GetBaud_RB    ENDP
  500.  
  501.  
  502. ; skip returns if no character available at port,
  503. ; otherwise returns with char in al, # of chars in buffer in dx.
  504. PrtChr_RB  PROC    NEAR
  505.     call chkxon        ; see if we have to xon the host.
  506.     cmp count,0
  507.     jnz prtch2
  508.     jmp rskp        ; No data - check console.
  509. prtch2:    mov si,savesi
  510.     lodsb            ; get a byte
  511.     cmp si,offset Source + bufsiz    ; bigger than buffer?
  512.     jb prtch1        ; no, keep going
  513.     mov si,offset Source    ; yes, wrap around
  514. prtch1:    dec count
  515.     mov savesi,si 
  516.     mov dx,count        ; return # of chars in buffer
  517.     ret
  518. PrtChr_RB  ENDP
  519.  
  520. ; local routine to see if we have to transmit an xon
  521. chkxon    proc    near
  522.     push    bx
  523.     mov    bx,portval
  524.     cmp    [bx].floflg,0    ; doing flow control?
  525.     je    chkxo1        ; no, skip all this
  526.     cmp    xofsnt,false    ; have we sent an xoff?
  527.     je    chkxo1        ; no, forget it
  528.     cmp    count,mntrgh    ; below trigger?
  529.     jae    chkxo1        ; no, forget it
  530.     mov    ax,[bx].flowc    ; ah gets xon
  531.     call    OutChr_RB        ; send it
  532.     nop
  533.     nop
  534.     nop            ; in case it skips
  535.     mov    xofsnt,false    ; remember we've sent an xon.
  536. chkxo1:    pop    bx        ; restore register
  537.     ret            ; and return
  538. chkxon    endp
  539.  
  540. ; Send a break out the current serial port.  Returns normally.
  541. SendBR_RB    PROC    NEAR
  542.     push bx
  543.     push cx
  544.     push dx
  545.     push ax
  546.     mov ah,ioctl
  547.     mov al,3        ; write to control channel.
  548.     mov bx,3        ; aux port handle
  549.     mov dx,offset iobuf
  550.     mov iobuf,stbrk        ; start sending a break
  551.     int dos
  552.     xor cx,cx        ; clear loop counter
  553. pause:    loop pause        ; Wait a while.
  554.     mov ah,ioctl
  555.     mov al,3
  556.     mov bx,3
  557.     mov dx,offset iobuf
  558.     mov iobuf,enbrk        ; stop sending the break
  559.     int dos
  560.     pop ax
  561.     pop dx
  562.     pop cx
  563.     pop bx
  564.     ret            ; And return.
  565. SendBR_RB    ENDP
  566.  
  567. ; Position the cursor according to contents of DX:
  568. ; DH contains row, DL contains column.  Returns normally.
  569.  
  570. PosCur_RB    PROC    NEAR
  571.     add    dx,101H        ; start at 1,1
  572.     push    es
  573.     push    dx
  574.     cld
  575.     mov    ax,ds
  576.     mov    es,ax        ; address right segment
  577.     mov    di,offset rowp
  578.     mov    al,dh        ; row comes first
  579.     mov    ah,0
  580.     call    nout
  581.     mov    al,';'
  582.     stosb            ; separated by a semi
  583.     pop    dx
  584.     mov    al,dl
  585.     mov    ah,0
  586.     call    nout
  587.     mov    al,'H'
  588.     stosb            ; end w/H
  589.     mov    byte ptr [di],'$' ; and dollar sign
  590.     mov    dx,offset gopos
  591.     call    tmsg
  592.     pop    es
  593.     ret
  594. PosCur_RB    ENDP
  595.  
  596. ; Delete a character from the terminal.  This works by printing
  597. ; backspaces and spaces.  Returns normally.
  598.  
  599. DoDel_RB    PROC    NEAR
  600.     mov dx,offset delstr    ; Erase weird character.
  601.     jmp tmsg
  602. DoDel_RB    ENDP
  603.  
  604. ; Move the cursor to the left margin, then clear to end of line.
  605. ; Returns normally.
  606.  
  607. CtlU_RB    PROC    NEAR
  608.     mov dx,offset clrlin    ; this just goes to left margin...
  609.     call tmsg
  610.     jmp ClearL_RB        ; now clear line
  611. CtlU_RB    ENDP
  612.  
  613. ; set the current port.
  614.  
  615. Coms_RB    PROC    NEAR
  616.     mov    dx,offset nyimsg
  617.     jmp    tmsg
  618. Coms_RB    ENDP
  619.  
  620. ; Set heath emulation on/off.
  621.  
  622. VTS_RB    PROC    NEAR
  623.     mov    dx,offset nyimsg
  624.     jmp    tmsg
  625. VTS_RB    ENDP
  626.  
  627. ; initialization for using serial port.  This routine performs
  628. ; any initialization necessary for using the serial port, including
  629. ; setting up interrupt routines, setting buffer pointers, etc.
  630. ; Doing this twice in a row should be harmless (this version checks
  631. ; a flag and returns if initialization has already been done).
  632. ; SerRst_RB below should restore any interrupt vectors that this changes.
  633. ; Returns normally.
  634.  
  635. SerIni_RB    PROC    NEAR
  636.     push es
  637.     cmp portin,0        ; Did we initialize port already? [21c]
  638.     jne serin0        ; Yes, so just leave. [21c]
  639.     cli            ; Disable interrupts
  640.     cld            ; Do increments in string operations
  641.     xor ax,ax        ; Address low memory
  642.     mov es,ax
  643.     mov ax,es:[4*serchn]    ; get old serial handler
  644.     mov oldser,ax        ; save.
  645.     mov ax,es:[4*serchn+2]    ; get segment
  646.     mov oldseg,ax        ; save segment as well
  647.     mov ax,es:[4*serch1]    ; this is alternate for older rainbows
  648.     mov old1ser,ax
  649.     mov ax,es:[4*serch1+2]
  650.     mov old1seg,ax        ; pretty silly, huh?
  651.     mov ax,offset serint    ; point to our routine
  652.     mov word ptr es:[4*serchn],ax ; point at our serial routine
  653.     mov word ptr es:[4*serch1],ax ; have to set both of these
  654.     mov es:[4*serchn+2],cs    ; our segment
  655.     mov es:[4*serch1+2],cs
  656.     mov al,0F0h        ; [DTR] enable RTS and DTR
  657.     out mnctrl,al        ; [DTR]
  658.     mov portin,1        ; Remember port has been initialized.
  659.     call ClrBuf_RB        ; Clear input buffer. 
  660.     sti            ; Allow interrupts
  661. serin0:    pop es
  662.     ret            ; We're done.
  663. SerIni_RB    ENDP
  664.  
  665. ; this is used to by SerIni_RB
  666. prtset    proc    near
  667.     lodsb            ; get a byte
  668.     or    al,al
  669.     jz    prtse1        ; end of table, stop here
  670.     out    dx,al        ; else send it out
  671.     jmp    prtset        ; and keep looping
  672. prtse1:    ret            ; end of routine
  673. prtset    endp
  674.  
  675. ; Reset the serial port.  This is the opposite of SerIni_RB.  Calling
  676. ; this twice without intervening calls to SerIni_RB should be harmless.
  677. ; Returns normally.
  678.  
  679. SerRst_RB    PROC    NEAR
  680.     push es            ; preserve this
  681.     cmp portin,0        ; Reset already? 
  682.     je srst1        ; Yes, just leave. 
  683.     cli            ; Disable interrupts
  684.     xor ax,ax
  685.     mov es,ax        ; address segment 0
  686.     mov ax,oldser
  687.     mov es:[4*serchn],ax
  688.     mov ax,oldseg
  689.     mov es:[4*serchn+2],ax
  690.     mov ax,old1ser
  691.     mov es:[4*serch1],ax
  692.     mov ax,old1seg
  693.     mov es:[4*serch1+2],ax    ; restore old handlers
  694.     mov portin,0        ; Reset flag.
  695. srst1:    pop es
  696.     ret            ; All done.
  697. SerRst_RB    ENDP
  698.  
  699.  
  700. Drop_DTR_RB PROC
  701.  
  702. ; This is just a guess on how to do this ... but, the following two lines
  703. ;  of code seem to be the ones which turn on RTS and DTR.  Lets try using
  704. ;  the opposite (?) to turn off those signals.
  705. ;
  706. ;    mov al,0F0h        ; [DTR] enable RTS and DTR
  707. ;    out mnctrl,al        ; [DTR]
  708.  
  709.     push ax            ; Save reg
  710.     sub al, al        ; Make a zero
  711.     out mnctrl, al        ; Try to turn off DTR and RTS
  712.     pop ax            ; Restore reg
  713.     ret            ; Done here
  714.  
  715. Drop_DTR_RB ENDP
  716.  
  717.  
  718. %OUT >> About half way through source file
  719.  
  720. ; serial port interrupt routine.  This is not accessible outside this
  721. ; module, handles serial port receiver interrupts.
  722.  
  723. serint    PROC  NEAR
  724.     push bx
  725.     push dx
  726.     push ax
  727.     push es
  728.     push di
  729.     push ds
  730.     push bp
  731.     push cx
  732.     cld
  733.     mov ax,seg datas
  734.     mov ds,ax        ; address data segment
  735.     mov es,ax
  736.     mov di,srcpnt        ; Registers for storing data.
  737.     mov dx,mnstatb        ; Asynch status port.
  738.     mov al,0        ; innocuous value
  739.     out dx,al        ; send out to get into a known state...
  740.     mov al,2        ; now address register 2
  741.     out dx,al
  742.     in al,dx        ; read interrupt cause
  743.     cmp al,7        ; in range?
  744.     ja serin7        ; no, just dismiss (what about reset error?)
  745.     mov bl,al
  746.     shl bl,1        ; double for word index
  747.     mov bh,0
  748.     call ivec[bx]        ; call appropriate handler
  749. serin7:    mov dx,mnstata        ; reload port address
  750.     mov al,38H
  751.     out dx,al        ; tell the port we finished with the interrupt
  752.     pop cx
  753.     pop bp
  754.     pop ds
  755.     pop di
  756.     pop es
  757.     pop ax
  758.     pop dx
  759.     pop bx
  760. intret:    iret
  761.  
  762. ; handler for serial receive, port A
  763. srcva:    mov dx,mnstata
  764.     mov al,0
  765.     out dx,al        ; put into known state...
  766.     in al,dx
  767.     test al,rxrdy        ; Data available?
  768.     jnz srcva1        ; yes, go read it
  769.     jmp srcva7
  770. srcva1:    mov al,30H        ; reset any errors
  771.     out dx,al
  772.     mov dx,mndata
  773.     in al,dx        ; read the character
  774.     cmp telflg,0        ; File transfer or terminal mode?
  775.     jz srcva2
  776.     and al,7FH        ; Terminal mode (7 bits only). 
  777.  
  778. srcva2: or al,al
  779.     jz srcva7        ; Ignore nulls.
  780.     cmp al,7FH        ; Ignore rubouts, too.
  781.     jz srcva7
  782.     mov ah,al
  783.     and ah,7fH        ; only consider low-order 7 bits for flow ctl.
  784.     mov bp,portval
  785.     cmp ds:[bp].floflg,0    ; Doing flow control?
  786.     je srcva4        ; Nope.
  787.     mov bx,ds:[bp].flowc    ; Flow control char (BH = XON, BL = XOFF).
  788.     cmp ah,bl        ; Is it an XOFF?
  789.     jne srcva3        ; Nope, go on.
  790.     mov xofrcv,true        ; Set the flag.
  791.     jmp short srcva7
  792. srcva3:    cmp ah,bh        ; Get an XON?
  793.     jne srcva4        ; No, go on.
  794.     mov xofrcv,false    ; Clear our flag.
  795.     jmp srcva7
  796. srcva4:    stosb
  797.     cmp di,offset Source + bufsiz
  798.     jb srcva5        ; not past end...
  799.     mov di,offset Source    ; wrap buffer around
  800. srcva5:    mov srcpnt,di        ; update ptr
  801.     inc count
  802.     cmp ds:[bp].floflg,0    ; Doing flow control?
  803.     je srcva7        ; No, just leave.
  804.     cmp xofsnt,true        ; Have we sent an XOFF?
  805.     je srcva7        ; Yes.
  806.     cmp count,mntrgh    ; Past the high trigger point?
  807.     jbe srcva7        ; No, we're within our limit.
  808.     mov ah,bl        ; Get the XOFF.
  809.     call OutChr_RB        ; Send it.
  810.     nop
  811.     nop
  812.     nop            ; ignore failure.
  813.     mov xofsnt,true        ; Remember we sent it.
  814. srcva7:    ret
  815.  
  816. ; The interrupt is for the 'B' port - transfer control to
  817. ; the original handler and hope for the best.
  818. tranb:    pushf            ; put flags on stack to simulate interrupt
  819.     call    dword ptr [old1ser] ; call old handler
  820.     ret            ; and return
  821.  
  822. stxa:    mov    dx,mnstata
  823.     mov    al,28H        ; reset transmit interrupt
  824.     out    dx,al
  825.     ret
  826.  
  827. sstata:    mov    dx,mnstata
  828.     mov    al,10H        ; reset status interrupt
  829.     out    dx,al
  830.     ret
  831.  
  832. SERINT    ENDP
  833.  
  834. ; Produce a short beep.  Returns normally.
  835.  
  836. Beep_RB    PROC    NEAR
  837.     mov dl,bell
  838.     mov ah,conout
  839.     int dos
  840.     ret
  841. Beep_RB    ENDP 
  842.  
  843. ; put the number in ax into the buffer pointed to by di.  Di is updated
  844. nout    proc    near
  845.     mov    dx,0        ; high order is always 0.
  846.     mov    bx,10
  847.     div    bx        ; divide to get digit
  848.     push    dx        ; save remainder digit
  849.     or    ax,ax        ; test quotient
  850.     jz    nout1        ; zero, no more of number
  851.     call    nout        ; else call for rest of number
  852. nout1:    pop    ax        ; get digit back
  853.     add    al,'0'        ; make printable
  854.     stosb            ; drop it off
  855.     ret            ; and return
  856. nout    endp
  857.  
  858.  
  859. Term_RB    proc    near
  860.     mov si,ax        ; this is source
  861.     mov di,offset ourarg    ; place to store arguments
  862.     mov ax,ds
  863.     mov es,ax        ; address destination segment
  864.     mov cx,size termarg
  865.     cld
  866.     rep movsb        ; copy into our arg blk
  867.     Test ourflgs, Which_mode    ; Are we at terminal emulation screen
  868.     jZ terma            ; Yes - so don't save it as BTLink 
  869.                     ;  command screen
  870.     call Save_command_mode_screen    ; Save BTLink command screen
  871. terma:    Cmp inited, 0        ; Inited yet?
  872.     jNE term0        ; Yes - skip message
  873.     Call CmBlnk_RB        ; Blank screen
  874.     Mov ah, PrSTR
  875.     Mov dx, OFFSET Terminal_message
  876.     Int Dos            ; Display message telling user how to get back
  877.                 ;  to Local BTLink
  878. term0:    cmp inited,0        ; inited yet?
  879.      jz term1        ; no, keep going
  880.  
  881.     test ourarg.flgs,scrsam    ; do they want us to leave it alone?
  882.      jnz term1        ; yes, skip redisplay.
  883.  
  884.     call rstscr        ; restore screen
  885.  
  886. term1:    mov inited,1        ; remember inited
  887.  
  888. TRM_Scr:
  889.     call PrtChr_RB
  890.      jmp SHORT term3    ; Have a char...
  891.      nop
  892.  
  893.     jmp SHORT term6        ; No char, go on
  894.  
  895. term3:    and al, 7fh        ; Turn off parity for terminal
  896.  
  897. ; We just got a char from the host, so if we are running under control of a
  898. ;  script we need to let the script processor know what that character is.
  899.  
  900.     cmp Script_processor, 0    ; Is there a script processor to run?
  901.      je PCH_No_script    ;  No
  902.  
  903.     push ax            ; Save reg
  904.     mov ah, 1        ; Code for "character" entry
  905.     call Script_processor    ; Let it do its thing
  906.     pop ax            ; Restore reg
  907.  
  908. PCH_No_script:
  909.     mov bx,offset ansbk1    ; Check for Escape Sequence
  910.     call ansbak        
  911.     mov bx,offset ansbk2    ; Check for Escape Sequence
  912.     call ansbak
  913.     mov bx,offset ansbk3    ; Check for Escape Sequence
  914.     call ansbak
  915.     mov bx,offset ansbk4    ; Check for Escape Sequence
  916.     call ansbak
  917.     mov bx,offset ansbk5    ; Check for Escape Sequence
  918.     call ansbak
  919.     mov bx,offset ansbk6    ; Check for Escape Sequence
  920.     call ansbak
  921.     Test    Ourflgs, MC_Pcon    ; Printer Controller on?
  922.      jNZ    Term5A        ; Yes - print character without displaying it
  923. term4:    push ax
  924.     int fastcon        ; go print it
  925.     pop ax
  926.     test ourarg.flgs,capt    ; capturing output?
  927.     jz term5        ; no, forget it
  928.     push ax
  929.     call ourarg.captr    ; else call the routine
  930.     pop ax
  931. term5:    test ourflgs,fpscr    ; print screen toggled on?
  932.     jz term6        ; no, keep going
  933. Term5A:    mov dl,al
  934.     mov ah,lstout        ; printer output
  935.     int dos
  936. term6:
  937.  
  938. ; Before we are allowed to really check the keyboard, we have to see if
  939. ;  we are running under control of a script.  If we are, we have to call
  940. ;  it at its "keyboard" entry instead of reading from the keyboard.
  941.  
  942.     cmp Script_processor, 0    ; Is there a script processor to run?
  943.      je TRM_No_script    ;  No
  944.  
  945. TRM_Ck:
  946. ;    mov ah, 1        ; Code to see if anything there
  947. ;    int Kb            ; Check input buffer
  948. ;     jz Trm_S1        ;  No chars
  949.  
  950. ;    sub ah, ah        ; Code zero
  951. ;    int Kb            ; Get the char from the buffer
  952.  
  953. ;    cmp al, 3        ; Control-C?
  954. ;     jne TRM_Ck        ;  No, go see if more chars to be read
  955.  
  956. ;    mov ah, 2        ; Code to shut down
  957. ;    jmp SHORT TRM_S2    ; Join common code
  958.  
  959. TRM_S1:
  960.     sub ah, ah        ; Code for "keyboard" entry
  961.  
  962. TRM_S2:
  963.     call Script_processor    ; Let it do its thing
  964.     test Quit_emulator, 1    ; Is this flag set?
  965.      jnz TRM_S3        ;  Yes
  966.  
  967.     jmp TRM_Scr        ; No, try for more port characters
  968.  
  969. TRM_S3:    call Close_Screen_RB    ; Go set things up right for command mode
  970.     jmp SHORT TRM_Quit    ; Go back to other program
  971.  
  972. TRM_No_script:
  973.     mov di,6        ; get level 1 character
  974.     push es
  975.     int firmwr
  976.     pop es            ; don't let firmware steal registers.
  977.     cmp cl,0ffh        ; character available?
  978.     je term7        ; Yes - go process it
  979.     cmp cl,1        ; maybe level 2 sequence around
  980.      je TRM_K1        ;  Yes, there is
  981.  
  982.     jmp TRM_Scr        ; No, forget it
  983.  
  984. TRM_K1:    mov di,2        ; get level 2 character
  985.     push es
  986.     int firmwr
  987.     pop es
  988.     cmp cl,0ffh        ; did we really get one?
  989.      je Term8a        ; Yes - send char to host,probably some type of
  990.                 ;  answerback, e.g. cursor position report
  991.  
  992.     jmp TRM_Scr        ; No, something strange happening
  993.  
  994. term7:    test ax,fnkey        ; function-type key?
  995.     jnz term8        ; yes, can't be escape character, but may
  996.                 ;  be Quit_emulator (DO) key or
  997.                 ;  Control-Break key
  998.     cmp al,ourarg.escc    ; escape char?
  999.     je TRM_Quit        ; yes, exit
  1000.     jmp CtlBRK        ; No - go check for Control-Break key
  1001. term8:    cmp al, 1        ; Is it the DO key?
  1002.      je term9        ; Yes - go set flag to exit emulator and exit
  1003. CtlBRK:    test ax, ctlkey        ; Control-type key?
  1004.      jz term8A        ; No - can't be Control-Break, go process char
  1005.     cmp al, brkkey        ; Yes - but is it the Break key?
  1006.      jne term8A        ; No - go process char
  1007.                 ; Yes - handle Control-Break as a special case
  1008.                 ;  we have the rainbow transmit the answerback
  1009.                 ;  stored in SETUP mode (This will supersede
  1010.                 ;  the 'SET KEY' feature!!!)
  1011.     Mov di, 0
  1012.     Mov al, Cntrl_E        ; ENQ character
  1013.     push es
  1014.     Int firmwr        ; Send ENQ so Rainbow will transmit its REAL
  1015.     pop es            ;  ANWSERBACK (if user defined one with 
  1016.     jmp term6        ;   SETUP) - and go process it
  1017.  
  1018. term8A:    call trnout        ; perform necessary translations, output char
  1019.     jmp TRM_Scr        ; and loop around
  1020. term9:    or Quit_Emulator, 1    ; Flag that we're exiting terminal emulation
  1021.  
  1022. TRM_Quit:
  1023.     call savscr        ; save terminal session screen
  1024.  
  1025.     cmp Script_processor, 0    ; Is there a script processor active?
  1026.      je TRM_q_no_script    ;  No
  1027.  
  1028.     mov ah, 2        ; Code to shutdown
  1029.     call Script_processor    ; Shut him down
  1030.  
  1031. TRM_q_no_script:
  1032.     test Quit_Emulator, 1    ; Are we exiting the emulator via the DO key
  1033.      jZ term9B        ; No - go get 2nd char
  1034.  
  1035.     Call Restore_command_mode_screen    ; Yes - bring back screen
  1036.     ret            ; and return with exit emulator flag set on
  1037.  
  1038. term9B:    Mov dx, OFFSET Escape_key_mode_line
  1039.     Call PutMod_RB        ; Display a mode line for 2nd char posibilities
  1040.  
  1041. term9C:    Mov di, 4
  1042.     Push es
  1043.     Int Firmwr        ; Look-ahead for a char without removing it
  1044.                 ;  from the input buffer (pretty neat!)
  1045.     Pop es
  1046.     Cmp cl, 0        ; Saw a char?
  1047.      jE term9C        ; No - keep looking
  1048.  
  1049.     Call ClrMod_RB        ; Yes - clear mode line and
  1050.     Call RstScr        ; Restore terminal screen after clearing mode
  1051.                 ;  line
  1052.     Ret            ; return to process 2nd char (C-Close,
  1053.                 ;  S-Status, B-Break, etc.)
  1054. Term_RB    endp
  1055.  
  1056.  
  1057. ; Set up to run a script processor at selected times, or clear it with zero
  1058.  
  1059. Set_up_script_processor_RB PROC
  1060.  
  1061.     mov Script_Processor, ax ; Set this up, or zero it out
  1062.     ret            ; That was easy
  1063.  
  1064. Set_up_script_processor_RB ENDP
  1065.  
  1066.  
  1067. ; enter with current terminal character in al, answerback ptr in bx.
  1068. ; calls answerback routine if necessary.
  1069. ; This can be used to make the emulator recognize any sequence.
  1070. ansbak    proc    near
  1071.     push    ax        ; preserve this
  1072.     mov    si,[bx].anspt    ; get current pointer
  1073.     cmp    al,[si]        ; is it correct?
  1074.     jne    ansba1        ; no, reset pointers and go on
  1075.     inc    [bx].anspt    ; increment pointer
  1076.     dec    [bx].ansct    ; decrement counter
  1077.     jnz    ansba2        ; not done, go on
  1078.     push    bx
  1079.     call    [bx].ansrtn    ; send answerback
  1080.     pop    bx
  1081. ansba1:    mov    ax,[bx].ansseq    ; get original sequence
  1082.     mov    [bx].anspt,ax
  1083.     mov    al,[bx].anslen    ; and length
  1084.     mov    [bx].ansct,al
  1085. ansba2:    pop    ax
  1086.     ret
  1087. ansbak    endp
  1088.  
  1089. ; Process the receipt of a "Media Copy (Printer Controller On) (MC)" escape
  1090. ;  sequence or a "Media Copy (Printer Controller Off) (MC)" escape sequence
  1091.  
  1092. Printer_Controller_MC    Proc    Near
  1093.     Xor    Ourflgs, MC_Pcon    ; Toggle Printer Controller flag
  1094.     Ret                ;  and return
  1095. Printer_Controller_MC    Endp
  1096.  
  1097. ; enable alternate keypad mode
  1098. enaaky    proc    near
  1099.     mov    akeyflg,1    ; remember alternate mode
  1100.     mov    keyptr,offset altktrn ; set correct translate table
  1101.     ret
  1102. enaaky    endp
  1103.  
  1104. ; disable alternate keypad mode
  1105. deaaky    proc    near
  1106.     mov    akeyflg,0
  1107.     mov    keyptr,offset keytrn
  1108.     ret
  1109. deaaky    endp
  1110.  
  1111. ; enter with char and flags in ax.  Does any necessary character translations,
  1112. ; then outputs character
  1113. trnout    proc    near
  1114.     and ax,not cplk        ; forget about caps lock key
  1115.     test ourarg.flgs,havtt    ; any translate table?
  1116.     jz trnou2        ; no, just output normally
  1117.     mov cx,ourarg.klen
  1118.     mov di,ourarg.ktab    ; get redefined keys
  1119.     repne scasw        ; look for this one
  1120.     jne trnou2        ; not found, try something else
  1121.     sub di,ourarg.ktab
  1122.     sub di,2        ; get index
  1123.     add di,ourarg.krpl    ; get translation address
  1124.     mov si,[di]        ; this is translation
  1125.     mov cl,[si]
  1126.     inc si            ; pick up length, increment past it
  1127.     mov ch,0
  1128.     jcxz trnou6        ; no translation, just return
  1129. trnou1:    lodsb            ; get a char
  1130.     push si
  1131.     push cx
  1132.     call sndhst        ; send the character
  1133.     pop cx
  1134.     pop si
  1135.     loop trnou1        ; loop thru rest of translation
  1136.     ret            ; and return
  1137. trnou2:    test ax,fnkey        ; function key?
  1138.     jz trnou5        ; no, keep going
  1139.     and ax,not fnkey    ; turn off function bit.
  1140.     mov di,offset spckey    ; our special keys
  1141.     mov cx,spclen        ; length of special key table
  1142.     repne scasw        ; look for it in our table
  1143.     jne trnou3        ; not found, maybe arrow key...
  1144.     sub di,offset spckey+2    ; get index
  1145.     call spchnd[di]        ; call appropriate handler
  1146.     ret            ; and return
  1147. trnou3:    mov di,offset arrkey    ; look for an arrow-type key...
  1148.     mov cx,arrlen        ; length of arrow key table
  1149.     repne scasb        ; is it an arrow key?
  1150.     jne trnou4        ; no, forget it
  1151.     sub di,offset arrkey+1    ; get index into table
  1152.     shl di,1        ; double for word index
  1153.     mov si,arrtrn[di]    ; get translation
  1154.     mov cl,[si]
  1155.     inc si
  1156.     mov ch,0
  1157.     jmp trnou1        ; go send translation
  1158. trnou4:    mov di,offset keypad    ; look for a keypad key.
  1159.     mov cx,keypln
  1160.     repne scasb        ; is it in keypad?
  1161.     jne trnou6        ; no, forget it
  1162.     sub di,offset keypad+1
  1163.     add di,keyptr        ; index into correct translation table
  1164.     mov al,[di]        ; get translation
  1165.     cmp akeyflg,0        ; in alternate keypad mode?
  1166.     je trnou5        ; no, just send the char
  1167.     push ax            ; else save the character
  1168.     mov al,esc
  1169.     call sndhst
  1170.     mov al,'O'
  1171.     call sndhst        ; send prefix
  1172.     pop ax            ; get the character back and fall thru...
  1173. trnou5:    call sndhst        ; send the character
  1174. trnou6:    ret
  1175. trnout    endp
  1176.  
  1177.  
  1178. ; handle the print screen key
  1179. prtscr    proc    near
  1180.     push    ds        ; save data segment
  1181.     mov    ax,scrseg
  1182.     mov    ds,ax        ; address screen segment
  1183.     mov    cx,slen        ; # of lines on screen
  1184.     mov    bx,0        ; current line #
  1185. prtsc1:    push    cx        ; save counter
  1186.     push    bx        ; and line ptr
  1187.     mov    si,ds:[latofs+bx] ; get ptr to line
  1188.     mov    cx,swidth    ; max # of chars/line
  1189.     mov    di,offset prbuf    ; print buffer
  1190. prtsc2:    lodsb            ; get a byte
  1191.     or    al,al        ; is it a null?
  1192.     jne    prtsc3        ; no, go on
  1193.     mov    al,' '        ; yes, replace by space
  1194. prtsc3:    stosb            ; drop it off
  1195.     cmp    al,' '        ; is it a space?
  1196.     je    prtsc4        ; yes, go on
  1197.     mov    dx,cx        ; else remember count at last non-space
  1198. prtsc4:    cmp    al,0ffH        ; end of line?
  1199.     loopne    prtsc2        ; continue if not end
  1200.     mov    cx,dx        ; count at last non-space, plus 1
  1201.     neg    cx
  1202.     add    cx,swidth    ; figure out # of chars to print
  1203.     mov    dx,offset prbuf
  1204.     push    ds        ; save this temporarily
  1205.     mov    ax,es
  1206.     mov    ds,ax        ; address data segment to print
  1207.     jcxz    prtsc5        ; 0 length, keep going
  1208.     mov    bx,4        ; standard printer device
  1209.     mov    ah,writef2    ; write call
  1210.     int    dos        ; write to the printer
  1211. prtsc5:    mov    ah,writef2
  1212.     mov    bx,4
  1213.     mov    dx,offset crlf
  1214.     mov    cx,2
  1215.     int    dos        ; follow line with a crlf
  1216.     pop    ds
  1217.     pop    bx
  1218.     pop    cx        ; restore counters
  1219.     add    bx,2        ; point to next line
  1220.     loop    prtsc1        ; and keep going
  1221.     pop    ds        ; restore registers
  1222.     ret            ; and return
  1223. prtscr    endp
  1224.  
  1225. ; toggle print flag...
  1226. togprt    proc    near
  1227.     xor    ourflgs,fpscr    ; toggle flag
  1228.     ret            ; and return
  1229. togprt    endp
  1230.  
  1231. ; Send a character to the host, handle local echo
  1232. sndhst    proc    near
  1233.     push ax            ; save the character
  1234.     mov ah,al
  1235.     call OutChr_RB
  1236.     nop
  1237.     nop
  1238.     nop
  1239.     pop ax
  1240.     test ourarg.flgs,lclecho ; echoing?
  1241.     jz sndhs2        ; no, exit
  1242.     int fastcon
  1243. sndhs2:    ret            ; and return
  1244. sndhst    endp
  1245.  
  1246.  
  1247. ; print a message to the screen.  Returns normally.
  1248. tmsg    proc    near
  1249.     mov    ah,prstr
  1250.     int    dos
  1251.     ret
  1252. tmsg    endp
  1253.  
  1254. ; save the screen for later
  1255. savscr    proc    near
  1256.     Mov    di, 8
  1257.     push    es
  1258.     Int    Firmwr        ; Disable cursor
  1259.     pop    es
  1260.     push    ds
  1261.     mov    ax,scrseg
  1262.     mov    ds,ax
  1263.     mov    cx,slen        ; # of lines to do
  1264.     mov    bx,0        ; current line #
  1265.     mov    di,offset ourscr ; place to save screen
  1266.     mov    dx,offset ourattr ; and to save attributes
  1267. savsc1:    push    cx        ; save current count
  1268.     mov    si,ds:[latofs+bx] ; get line ptr
  1269.     mov    cx,swidth    ; # of chars/line
  1270.     rep    movsb        ; copy it out
  1271.     mov    si,ds:[latofs+bx]
  1272.     add    si,1000H    ; this is where attributes start
  1273.     xchg    dx,di        ; this holds attribute ptr
  1274.     mov    cx,swidth    ; # of attrs to move
  1275.     rep    movsb
  1276.     xchg    dx,di
  1277.     pop    cx        ; restore counter
  1278.     add    bx,2        ; increment line ptr
  1279.     loop    savsc1        ; save all lines and attributes
  1280.     pop    ds
  1281.     call    savpos        ; might as well save cursor pos
  1282.     Mov    di, 0Ah
  1283.     push    es
  1284.     Int    Firmwr        ; Enable cursor
  1285.     pop    es
  1286.     ret
  1287. savscr    endp
  1288.  
  1289. ; restore the screen saved by savscr
  1290. rstscr    proc    near
  1291.     Mov    di, 8
  1292.     push    es
  1293.     Int    Firmwr        ; Disable cursor
  1294.     pop    es
  1295.     call    CmBlnk_RB    ; start by clearing screen
  1296.     mov    si,offset ourscr ; point to saved screen
  1297.     mov    dx,offset ourattr ; and attributes
  1298.     mov    cx,slen        ; # of lines/screen
  1299.     mov    bx,101H        ; start at top left corner
  1300. rstsc1:    push    bx
  1301.     push    cx
  1302.     push    si        ; save ptrs
  1303.     push    dx
  1304.     mov    ax,si        ; this is source
  1305.     call    prlina        ; print the line
  1306.     pop    dx
  1307.     pop    si
  1308.     pop    cx
  1309.     pop    bx
  1310.     add    si,swidth    ; point to next line
  1311.     add    dx,swidth    ; and next attributes
  1312.     inc    bx        ; address next line
  1313.     loop    rstsc1        ; keep restore lines
  1314.     call    rstpos        ; don't forget position
  1315.     Mov    di, 0Ah
  1316.     push    es
  1317.     Int    Firmwr        ; Enable cursor
  1318.     pop    es
  1319.     ret
  1320. rstscr    endp
  1321.  
  1322. ; save the command mode screen for later
  1323. Save_command_mode_screen    proc
  1324.     Mov    di, 8
  1325.     push    es
  1326.     Int    Firmwr        ; Disable cursor
  1327.     pop    es
  1328.     push    ds
  1329.     mov    ax,scrseg
  1330.     mov    ds,ax
  1331.     mov    cx,slen        ; # of lines to do
  1332.     mov    bx,0        ; current line #
  1333.     mov    di,offset command_mode_screen ; place to save screen
  1334.     mov    dx,offset command_mode_attrs ; and to save attributes
  1335. savcm1:    push    cx        ; save current count
  1336.     mov    si,ds:[latofs+bx] ; get line ptr
  1337.     mov    cx,swidth    ; # of chars/line
  1338.     rep    movsb        ; copy it out
  1339.     mov    si,ds:[latofs+bx]
  1340.     add    si,1000H    ; this is where attributes start
  1341.     xchg    dx,di        ; this holds attribute ptr
  1342.     mov    cx,swidth    ; # of attrs to move
  1343.     rep    movsb
  1344.     xchg    dx,di
  1345.     pop    cx        ; restore counter
  1346.     add    bx,2        ; increment line ptr
  1347.     loop    savcm1        ; save all lines and attributes
  1348.     pop    ds
  1349.     call    Command_savpos    ; might as well save cursor pos
  1350.     Mov    di, 0Ah
  1351.     push    es
  1352.     Int    Firmwr        ; Enable cursor
  1353.     pop    es
  1354.     And    ourflgs, NOT Which_mode        ; Flag that we're at terminal
  1355.                         ;  emulation screen now
  1356.     ret
  1357. Save_command_mode_screen    endp
  1358.  
  1359. ; Restore the command mode screen saved by Save_command_mode_screen
  1360. Restore_command_mode_screen    proc
  1361.     Or    ourflgs, Which_mode    ; Flag that were are at BTLink
  1362.                         ;  command screen
  1363.     Mov    di, 8
  1364.     push    es
  1365.     Int    Firmwr        ; Disable cursor
  1366.     pop    es
  1367.     call    CmBlnk_RB        ; start by clearing screen
  1368.     mov    si,offset command_mode_screen ; point to saved screen
  1369.     mov    dx,offset command_mode_attrs ; and attributes
  1370.     mov    cx,slen        ; # of lines/screen
  1371.     mov    bx,101H        ; start at top left corner
  1372. rstcm1:    push    bx
  1373.     push    cx
  1374.     push    si        ; save ptrs
  1375.     push    dx
  1376.     mov    ax,si        ; this is source
  1377.     call    prlina        ; print the line
  1378.     pop    dx
  1379.     pop    si
  1380.     pop    cx
  1381.     pop    bx
  1382.     add    si,swidth    ; point to next line
  1383.     add    dx,swidth    ; and next attributes
  1384.     inc    bx        ; address next line
  1385. loop    rstcm1        ; keep restore lines
  1386.     call    Command_rstpos    ; don't forget position
  1387.     Mov    di, 0Ah
  1388.     push    es
  1389.     Int    Firmwr        ; Enable cursor
  1390.     pop    es
  1391.     ret
  1392. Restore_command_mode_screen    endp
  1393.  
  1394. ; save cursor position
  1395. savpos    proc    near
  1396.     mov    dx,offset curinq ; where is the cursor?
  1397.     call    tmsg
  1398.     mov    posbuf,esc    ; put an escape in the buffer first
  1399.     mov    di,offset posbuf+1
  1400. savpo1:    mov    ah,8        ; read, no echo
  1401.     int    dos
  1402.     cmp    al,'R'        ; end of report?
  1403.     je    savpo2        ; yes
  1404.     stosb            ; no, save it
  1405.     jmp    savpo1        ; and go on
  1406. savpo2:    mov    al,'H'        ; this ends the sequence when we send it
  1407.     stosb
  1408.     mov    byte ptr [di],'$' ; need this to print it later
  1409.     ret            ; and return
  1410. savpos    endp
  1411.  
  1412. ; restore the position saved by savpos
  1413. rstpos    proc    near
  1414.     mov    dx,offset posbuf
  1415.     call    tmsg        ; just print this
  1416.     ret            ; and return
  1417. rstpos    endp
  1418.  
  1419. ; save command screen cursor position
  1420. Command_savpos    proc
  1421.     mov    dx,offset curinq ; where is the cursor?
  1422.     call    tmsg
  1423.     mov    command_posbuf,esc    ; put an escape in the buffer first
  1424.     mov    di,offset command_posbuf+1
  1425. csavpo1:mov    ah,8        ; read, no echo
  1426.     int    dos
  1427.     cmp    al,'R'        ; end of report?
  1428.     je    csavpo2        ; yes
  1429.     stosb            ; no, save it
  1430.     jmp    csavpo1        ; and go on
  1431. csavpo2:mov    al,'H'        ; this ends the sequence when we send it
  1432.     stosb
  1433.     mov    byte ptr [di],'$' ; need this to print it later
  1434.     ret            ; and return
  1435. Command_savpos    endp
  1436.  
  1437. ; restore the position saved by Command_savpos
  1438. Command_rstpos    proc
  1439.     mov    dx,offset command_posbuf
  1440.     call    tmsg        ; just print this
  1441.     ret            ; and return
  1442. Command_rstpos    endp
  1443.  
  1444. ; print a 0FFh-terminated line at most swidth long...  Pass the line in ax.
  1445. ; cursor position should be in bx.
  1446. ; prlina writes attributes as well, which should be passed in dx.
  1447. prlin    proc    near
  1448.     mov    bp,2        ; print characters only
  1449.     jmp    short prli1
  1450. prlina:    xor    bp,bp        ; 0 means print attributes as well.
  1451. prli1:    push    es        ; this trashes es!!!
  1452.     mov    si,ax        ; better place for ptr
  1453.     mov    di,ax        ; need it here for scan
  1454.     mov    cx,swidth    ; max # of chars in line
  1455.     mov    al,0ffh        ; this marks the end of the line
  1456.     repne    scasb        ; look for the end
  1457.     jne    prli2        ; not found
  1458.     inc    cx        ; account for pre-decrement
  1459. prli2:    neg    cx
  1460.     add    cx,swidth    ; figure out length of line
  1461.     jcxz    prli3        ; 0-length line, skip it.
  1462.     mov    ax,bp        ; writing characters and/or attributes
  1463.     mov    bp,ds        ; wants segment here
  1464.     mov    di,14H        ; fast write to screen
  1465.     int    firmwr        ; pos is in bx, char ptr in si
  1466. prli3:    pop    es        ; restore register
  1467.     ret            ; and return
  1468. prlin    endp
  1469.  
  1470.  
  1471. ; Jumping to this location is like retskp.  It assumes the instruction
  1472. ;   after the call is a jmp addr.
  1473.  
  1474. RSKP    PROC    NEAR
  1475.     pop bp
  1476.     add bp,3
  1477.     push bp
  1478.         ret
  1479. RSKP    ENDP
  1480.  
  1481. ; Jumping here is the same as a ret.
  1482.  
  1483. R       PROC    NEAR
  1484.         ret
  1485. R       ENDP
  1486.  
  1487. Do_Server_mode    PROC    NEAR    ; Remote BTLink sent magic escape
  1488.                     ;  sequence to throw us into Server
  1489.                     ;  mode while we were in TERMINAL MODE
  1490.     Call Savscr            ; Save the current screen
  1491.     Call Serrst_RB            ; Reset the serial port
  1492.     Call Enter_Server        ; Jump to Server code
  1493.      nop
  1494.      nop
  1495.      nop
  1496.     Call Serini_RB            ; Initialize the serial port
  1497.     Call Rstscr            ; Restore the user's terminal mode
  1498.                     ;  screen
  1499.     push dx                ; Save a reg
  1500.     mov dx, OFFSET Partial_esc_seq    ; The string to type
  1501.     Call Tmsg            ; Type it out so the "J" left over
  1502.                     ;  will be "eaten" by the firmware
  1503.     pop dx                ; Restore saved register
  1504.     Ret
  1505. Do_Server_mode    ENDP
  1506.  
  1507. Identify PROC
  1508.  
  1509.     push cx            ; Save some registers
  1510.     push si
  1511.  
  1512.     mov cx, Length_of_identification_sequence
  1513.     mov si, OFFSET Identification_sequence
  1514.  
  1515. Ident_LOP:
  1516.     lodsb            ; Get the next byte of the sequence
  1517.     push cx            ; Called routines clobber this reg
  1518.     call SndHst        ; Send the character to the host
  1519.     pop cx            ; Get back saved value
  1520.     loop Ident_LOP        ; Go do another character, if any
  1521.  
  1522.     pop si            ; Restore registers
  1523.     pop cx
  1524.     ret
  1525.  
  1526. Identify ENDP
  1527.  
  1528. Close_screen_RB    Proc    Near        ; Called when User quits emulator
  1529.     jmp Restore_command_mode_screen    ;  and enters Command Mode
  1530. Close_screen_RB    Endp
  1531.  
  1532. code    ends 
  1533.     end
  1534. 
  1535.